package org.example.rpc.core.socket.util;

import org.example.rpc.common.entity.RpcRequest;
import org.example.rpc.common.entity.RpcResponse;
import org.example.rpc.common.eunm.PackageType;
import org.example.rpc.common.eunm.RpcError;
import org.example.rpc.common.exception.RpcException;
import org.example.rpc.core.serializer.CommonSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;

public class ObjectReader {

    private static final Logger logger = LoggerFactory.getLogger(ObjectReader.class);
    public static final int MAGIC_NUMBER = 0xCAFEBABE;

    public static Object readObject(InputStream in) throws IOException {
        byte[] numberBytes = new byte[4];
        in.read(numberBytes);
        int magic = bytesToInt(numberBytes);
        if(magic != MAGIC_NUMBER){
            logger.error("协议错误：{}", magic);
            throw new RpcException(RpcError.UNKNOW_PROTOCAL);
        }
        in.read(numberBytes);
        int packageCode = bytesToInt(numberBytes);
        Class<?> packageClass;
        if(packageCode == PackageType.REQUEST_PACK.getCode()){
            packageClass = RpcRequest.class;
        }else if(packageCode == PackageType.RESPONSE_PACK.getCode()){
            packageClass = RpcResponse.class;
        }else{
            logger.error("不能识别的数据包：{}", packageCode);
            throw new RpcException(RpcError.UNKNOW_PACKAGE_TYPE);
        }
        in.read(numberBytes);
        int serializerCode = bytesToInt(numberBytes);
        CommonSerializer serializer = CommonSerializer.getByCode(serializerCode);
        if(serializer == null){
            logger.error("序列化器为空");
            throw new RpcException(RpcError.SERIALIZER_NOT_FOUND);
        }
        in.read(numberBytes);
        int length = bytesToInt(numberBytes);
        byte[] data = new byte[length];
        in.read(data);
        return serializer.deserialize(data, packageClass);

    }

    private static int bytesToInt(byte[] src) {
        int value;
        value = (src[0] & 0xFF)
                | ((src[1] & 0xFF)<<8)
                | ((src[2] & 0xFF)<<16)
                | ((src[3] & 0xFF)<<24);
        return value;
    }

}
